#include "HHFloodFill.h"
#include "ui_hhfloodfill.h"
#include <qmath.h>

HHFloodFill::HHFloodFill(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::HHFloodFill)
{
    ui->setupUi(this);

    m_strPath = QApplication::applicationDirPath() + "/teddy.png";
    m_image = QImage(m_strPath);
    m_resultImage = m_image;
    ui->label->setFixedSize(m_image.size());
    ui->label->setPixmap(QPixmap::fromImage(m_image));
    qDebug() << m_image.size();
}

HHFloodFill::~HHFloodFill()
{
    delete ui;
}

void HHFloodFill::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        m_image = m_resultImage;
        m_bPressed = true;
        m_pressedPos = event->pos();
        ScanLineSeedFill(m_pressedPos.x(), m_pressedPos.y(), m_image.pixelColor(m_pressedPos.x(), m_pressedPos.y()), 10);
        ui->label->setPixmap(QPixmap::fromImage(m_image));
    }

    QWidget::mousePressEvent(event);
}

void HHFloodFill::mouseMoveEvent(QMouseEvent *event)
{
    if(event->buttons() & Qt::LeftButton && m_bPressed)
    {
        QPoint pos = event->pos() - m_pressedPos;
        double d = qSqrt(pos.x() * pos.x() + pos.y() * pos.y());
        ScanLineSeedFill(m_pressedPos.x(), m_pressedPos.y(), Qt::red, int(d));
        ui->label->setPixmap( QPixmap::fromImage(m_image));

//        QImage image(m_strPath);
//        QColor color = image.pixelColor(m_pressedPos.x(), m_pressedPos.y());
//        ui->label->setPixmap(m_destPix1);
    }
}

void HHFloodFill::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton && m_bPressed)
    {
//        m_bPressed = false;
//        m_destPix = m_destPix1;
//        ui->label->setPixmap(m_destPix);
    }

    QWidget::mouseReleaseEvent(event);
}

void HHFloodFill::ScanLineSeedFill(int x, int y, QColor new_color, int iThresHold)
{
    qDebug() << "11111111111111111111111111111111";
    QStack<QPoint> seedStackDown;
    QStack<QPoint> seedStackUp;


    int count = FillLineRight(x, y, new_color, iThresHold);
    int xRight = x + count - 1;
    count = FillLineLeft(x - 1, y, new_color, iThresHold);
    int xLeft = x - count;

    //第4步，处理相邻两条扫描线
    SearchLineNewSeed(seedStackDown, xLeft, xRight, y - 1, new_color, iThresHold);
    SearchLineNewSeed(seedStackUp, xLeft, xRight, y + 1, new_color, iThresHold);


    while(!seedStackUp.isEmpty())
    {
        // 向上扫描
        QPoint seed = seedStackUp.pop(); //第2步，取当前种子点

        //第3步，向左右填充
        int count1 = FillLineRight(seed.x(), seed.y(), new_color, iThresHold);
        int xRight1 = seed.x() + count1 - 1;
        count = FillLineLeft(seed.x() - 1, seed.y(), new_color, iThresHold);
        int xLeft1 = seed.x() - count1;

        qDebug() << "111111111111111";

        //第4步，处理相邻两条扫描线
        SearchLineNewSeed(seedStackUp, xLeft1, xRight1, seed.y() - 1, new_color, iThresHold);
    }

    while(!seedStackDown.isEmpty())
    {
        qDebug() << "22222222222222";
        // 向下扫描
        QPoint seed = seedStackDown.pop(); //第2步，取当前种子点

        //第3步，向左右填充
        int count2 = FillLineRight(seed.x(), seed.y(), new_color, iThresHold);
        int xRight2 = seed.x() + count2 - 1;
        count = FillLineLeft(seed.x() - 1, seed.y(), new_color, iThresHold);
        int xLeft2 = seed.x() - count2;

        //第4步，处理相邻两条扫描线
        SearchLineNewSeed(seedStackDown, xLeft2, xRight2, seed.y() - 1, new_color, iThresHold);
    }
}

void HHFloodFill::SearchLineNewSeed(QStack<QPoint> &stk, int xLeft, int xRight, int y, QColor new_color, int iThresHold)
{
    int xt = xLeft;
    bool findNewSeed = false;
    while(xt <= xRight)
    {
        findNewSeed = false;
        QColor curColor = m_image.pixelColor(xt, y);
        bool bOk = checkColorIsOutBorder(new_color, curColor, iThresHold);
        while(bOk && (xt < xRight))
        {
            findNewSeed = true;
            xt++;
            curColor = m_image.pixelColor(xt, y);
            bOk = checkColorIsOutBorder(new_color, curColor, iThresHold);
        }

        if(findNewSeed)
        {
            qDebug() << xt << y <<  bOk << xLeft << xRight << m_pressedPos;
            if(bOk)
            {
               stk.push_back(QPoint(xt, y));
            }
            else
            {
                if(xt <= xRight)
                {
                    stk.push_back(QPoint(xt - 1, y));
                }
            }
        }

        int xspan = SkipInvalidInLine(xt, y, xRight, new_color, iThresHold);
        xt += (xspan == 0) ? 1 : xspan;
    }
}

int HHFloodFill::SkipInvalidInLine(int xt, int y, int xRight, QColor new_color, int iThresHold)
{
    int iNum = 0;
    QColor curColor = m_image.pixelColor(xt, y);
    bool bOk = checkColorIsOutBorder(new_color, curColor, iThresHold);

    while(xt <= xRight)
    {
        if(!bOk)
        {
            iNum ++;
            xt ++;
        }
        else
        {
            break;
        }
        curColor = m_image.pixelColor(xt, y);
        bOk = checkColorIsOutBorder(new_color, curColor, iThresHold);
    }

    return iNum;
}

int HHFloodFill::FillLineRight(int x, int y, QColor new_color, int iThresHold)
{
    int num = 0;
    QColor color = m_image.pixelColor(x, y);
    bool bOk = checkColorIsOutBorder(new_color, color, iThresHold);
    while(bOk)
    {
        m_image.setPixelColor(x,y, Qt::red);
        x++;
        num++;
        color = m_image.pixelColor(x, y);
        bOk = checkColorIsOutBorder(new_color, color, iThresHold);
    }

    return num;
}

int HHFloodFill::FillLineLeft(int x, int y, QColor new_color, int iThresHold)
{
    int num = 0;
    QColor color = m_image.pixelColor(x, y);
    bool bOk = checkColorIsOutBorder(new_color, color, iThresHold);
    while(bOk)
    {
        m_image.setPixelColor(x,y, Qt::red);
        x--;
        num++;
        color = m_image.pixelColor(x, y);
        bOk = checkColorIsOutBorder(new_color, color, iThresHold);
    }

    return num;
}

bool HHFloodFill::checkColorIsOutBorder( const QColor &refColor, const QColor &targetColor, const double &dThresHold)
{
    int iDelt = qAbs(refColor.red() - targetColor.red()) + qAbs(refColor.green() - targetColor.green())
            + qAbs(refColor.blue() - targetColor.blue());

    if(iDelt <= dThresHold)
    {
        return true;
    }

    return false;
}

void HHFloodFill::on_pushButton_clicked()
{

}

